//--------------------------------------------------------------------
//
//  Laboratory 3                                           ListArray.h
//  **Instructor's Solution**
//  Class declaration for the array implementation of the List ADT
//
//--------------------------------------------------------------------

#ifndef LISTARRAY_H
#define LISTARRAY_H

#include <stdexcept>
#include <iostream>

using namespace std;

template < typename DataType >
class List
{
protected:
   static const int DEFAULT_MAX_LIST_SIZE = 10;   // Default maximum list size

public:
   // Constructors
   List ( int maxNumber = DEFAULT_MAX_LIST_SIZE ) // Default constructor
   {
      maxSize = maxNumber;
      size = 0;
      cursor = 0;
      dataItems = new DataType[maxSize];
   }

   List ( const List& source )		// Copy constructor
   {
      this->maxSize = source.maxSize;
      this->size = source.size;
      this->cursor = source.cursor;
      this->dataItems = new DataType[this->maxSize];
      for (int ix = 0; ix < this->size; ix ++)
      {
         this->dataItems[ix] = source.dataItems[ix];
      }       
   }

   // Overloaded assignment operator
   List& operator= ( const List& source )
   {
      if (this == &source)
      {
         return *this;
      }
      if (this->maxSize != source.maxSize)
      {
         delete[] this->dataItems;
         this->dataItems = new DataType[source.maxSize];
      }
      this->maxSize = source.maxSize;
      this->cursor = source.maxSize;
      this->size = source.size;
      for (int ix = 0; ix < size; ix++)
      {
         this->dataItems[ix] = source.dataItems[ix];
      }
      return *this;
   }

   // Destructor
   virtual ~List ()
   {
      delete[] dataItems;
   }

   // List manipulation operations
   virtual void insert ( const DataType& newDataItem ) throw ( logic_error ) // Insert after cursor
   {
      if (size == maxSize)
      {
         throw logic_error("List full");
      }
      for (int ix = 0; ix < size - cursor; ix++)
      {
         dataItems[size - ix] = dataItems[(size - ix) - 1];
      }
      dataItems[cursor+1] = newDataItem;
      size++;
   }
   void remove () throw ( logic_error )        // Remove data item
   {
      if (cursor == maxSize)
      {
         throw logic_error("List full");
      }
      for (int ix = cursor; ix < size ; ix++)
      {
         dataItems[ix] = dataItems[ix + 1];
      }
      size--;
      cursor = min(cursor, size-1);       
   }

   virtual void replace ( const DataType& newDataItem ) throw ( logic_error ) // Replace data item
   {
      if (cursor == maxSize)
      {
         throw logic_error("List cannot contain any elements");
      }
      dataItems[cursor] = newDataItem;       
   }

   void clear()
   {
      cursor = size = 0;
   }

   // List status operations
   bool isEmpty () const                    // List is empty
   {
      return size == 0;
   }

   bool isFull () const                     // List is full
   {
      return size == maxSize;
   }

   // List iteration operations
   void gotoBeginning ()  throw ( logic_error )                    // Go to beginning
   {
      cursor = 0;
   }

   void gotoEnd ()                           // Go to end
      throw ( logic_error )
   {
      cursor = size - 1;
   }

   bool gotoNext ()                          // Go to next data item
      throw ( logic_error )
   {
      if (cursor < size + 1)
      {
         cursor ++;
         return true;
      }
      return false;
   }

   bool gotoPrior ()                         // Go to prior data item
      throw ( logic_error )
   {
      if (cursor > 0)
      {
         cursor--;
         return true;
      }
      return false;
   }

   DataType getCursor () const
      throw ( logic_error )                // Return data item
   {
      if (cursor == maxSize)
      {
         throw logic_error("List cannot contain any elements");
      }
      return dataItems[cursor];       
   }

   // Output the list structure -- used in testing/debugging
   virtual void showStructure () const
   {
   }

   // In-lab operations
   void moveToNth ( int n )                  // Move data item to pos. n
      throw ( logic_error )
   {
      if (n >= maxSize || n < 0)
         throw logic_error("Invalid cursor position");
      cursor = n;
   }

   bool find ( const DataType& searchDataItem )     // Find data item
      throw ( logic_error )
   {
      int ix = 0;
      while (ix < size)
      {
         if (dataItems[ix] == searchDataItem)
            return true;
      }
      return false;       
   }

protected:

   // Data members
   int maxSize,
      size,             // Actual number of data item in the list
      cursor;           // Cursor array index
   DataType *dataItems;  // Array containing the list data item
};

#endif

